//------------------------------------------------------------------------------ 
//  <copyright file="ImageOperations2DInterop.h" company="Microsoft Corporation">
// The MIT License (MIT)
// 
// Copyright (c) 2014, Microsoft Corporation
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.
//  </copyright>
//------------------------------------------------------------------------------
#pragma once

#include <vtcommon.h>
#include <vtnumerics.h>
#include <vtcore.h>
#include <vt_io.h>
#include "vtimgproc.h"
#include <vt_edgedetect.h>
#include <vt_linedetector.h>
#include "VisionTools/ImageEdgel.h"
#include "VisionTools/ImageEllipse.h"
#include "VisionTools/ImageLine.h"
#include "ImageFrame.h"
#include <sunflower.h>

using namespace System;
using namespace System::Collections::Generic;
using namespace System::Runtime::InteropServices;
using namespace System::Windows::Media::Imaging;
using namespace Microsoft::Robotics::Vision;

namespace Microsoft 
{
    namespace Robotics 
    {
        namespace Vision 
        {
            /// <summary> 
            /// Wrapper class for lower level vision tools library. 
			/// The image data and parameters can only be changed in the constructor, thus 
			/// facilitating caching of results.
			///
            /// Functionality wrapped will be updated as need dictates. Currently the following
            /// Functionality is wrapped
            ///  Edge, line curve ... detection in images
            /// </summary>
            public ref class ImageOperations2DInterop 
            {
            public:
                /// <summary>Gets a list of edgels found in image </summary>
				static List< ImageEdgel^ >^ GetEdgels(ImageFrameRgb^ image);

                /// <summary>Gets a list of curves found in image (which are fit to edgels).  Each curve is a sequence of edgels. </summary>
				static List< List< ImageEdgel ^> ^>^ GetCurves(ImageFrameRgb^ image);

				/// <summary>Gets a list of lines found in image (which are fit to curves) </summary>
				static List< ImageLine^ >^ GetLines(ImageFrameRgb^ image);

                /// <summary>Gets a list of ellipses found in image (which are fit to curves) </summary>
				static List< ImageEllipse^ >^ GetEllipses(ImageFrameRgb^ image);

				/// <summary>
				/// Creates a YUY2 image from a raw data buffer.
				/// This is not a constructor in the class because it is a special method that is only called by the camera.
				/// </summary>
				/// <param name="width">Image width.</param>
				/// <param name="height">Image height.</param>
				/// <param name="data">Pointer to data buffer.</param>
				/// <param name="lengthOfDataInBytes">Number of bytes in the data array.  Must be equal to width * height * 2, the latter being the BytesPerPixel.</param>
				/// <returns>Image whose array of pixel values is identical to those of the data buffer.</param>
				static ImageFrameYuy2^ CreateImageFrameYuy2FromRawDataBuffer(int width, int height, IntPtr data, int lengthOfDataInBytes);

				/// <summary>
				/// Creates a Gray8 image from a bitmap frame.  Throws an exception if the bitmap frame is not also gray8.
				/// </summary>
				/// <param name="bitmap">Bitmap frame.  Must be Gray8 type.</param>
				/// <returns>Image whose size and pixel values are identical to those of the bitmap frame.</param>
				static ImageFrameGray8^ CreateImageFrameGray8FromBitmapFrame(BitmapFrame^ bitmap);

				/// <summary>
				/// Load an image from disk.  Throws an exception if the image is not 24-bit RGB with no extra padding.
				/// </summary>
				/// <param name="filename">name of the file</param>
				/// <returns>image frame</returns>
				static ImageFrameRgb^ LoadImageRgbFromFile(System::String^ filename);

				/// <summary>
				/// Converts a YUY2 image frame into a regular RGB image
				/// </summary>
				/// <param name="yuy2Image">YUY2 image to convert</param>
				/// <returns>converted RGB image</returns>
				static ImageFrameRgb^ ConvertYUY2ToRGBImage(ImageFrameYuy2^ yuy2Image);

				/// <summary>
				/// Converts a YUY2 image frame into a Gray8 image
				/// </summary>
				/// <param name="yuy2Image">YUY2 image to convert</param>
				/// <returns>converted Gray8 image</returns>
				static ImageFrameGray8^ ConvertYUY2ToGray8Image(ImageFrameYuy2^ yuy2Image);

				/// <summary>
				/// Converts a RBG image frame into a Gray8 image
				/// </summary>
				/// <param name="yuy2Image">RGB image to convert</param>
				/// <returns>converted Gray8 image</returns>
				static ImageFrameGray8^ ConvertRGBToGray8Image(ImageFrameRgb^ yuy2Image);

				/// <summary>
                /// Clamp between high and low values
                /// </summary>
                ///<param name="bLow">Low byte value which forms the lower limit for clamping</param>
                ///<param name="bHigh">High byte value which forms the upper limit for clamping</param>
                ///<param name="nVal">The value to be clamped</param>
                ///<returns>Clamped value</returns>                
                static int Clamp(int bLow, int bHigh, int nVal);

                /// <summary>
                /// YUY2 to Luminance Conversion
                /// </summary>
                ///<param name="pRGB">YUY2 byte array containing the image, input - caller allocates memory</param>
                ///<param name="cbLengthRGB">Length of the RGB image array in bytes</param>
                ///<param name="pLum">Luminance byte array containing the image, output - caller allocates memory</param>
                ///<param name="cbLengthLum">Length of the Lum image array in bytes</param>                   
                static void YUY2ToLum(UINT8* pYUY2, DWORD cbLengthYUY2, UINT8* pLum, DWORD cbLengthLum);

                /// <summary>
                /// YUY2 to RGB Conversion from MSDN
                /// http://msdn.microsoft.com/en-us/library/aa917087.aspx
                /// </summary>
                ///<param name="pYUY2">YUY2 byte array containing the image, input - caller allocates memory</param>
                ///<param name="cbLengthYUY2">Length of the YUY2 image array in bytes</param>
                ///<param name="pRGB">RGB byte array containing the image, output - caller allocates memory</param>
                ///<param name="cbLengthRGB">Length of the RGB image array in bytes</param>
                static void YUY2ToRGB(UINT8* pYUY, DWORD cbLengthYUY2, UINT8* pRGB, DWORD cbLengthRGB);

                /// <summary>
                /// RGB to Lum Conversion
                /// </summary>
                ///<param name="pRGB">pRGB byte array containing the image, input - caller allocates memory</param>
                ///<param name="cbLengthRGB">Length of the RGB image array in bytes</param>
                ///<param name="pLum">Lum byte array containing the image, output - caller allocates memory</param>
                ///<param name="cbLengthLum">Length of the Lum image array in bytes</param>
                static void RGBToLum(UINT8* pRGB, DWORD cbLengthRGB, UINT8* pLum, DWORD cbLengthLum);

				/// <summary>
				/// Finds feature points in a gray scale image
				/// </summary>
				/// <param name="image">The grayscale image</param>
				/// <param name="width">Width of the image</param>
				/// <param name="height">Height of the image</param>
				/// <param name="stride">Stride, in bytes, of a row</param>
				/// <param name="maxFeatures">Maximum number of features</param>
				/// <param name="x">Array of x coordinates of feature points</param>
				/// <param name="y">Array of y coordinates of feature points</param>
				/// <param name="detector">The type of feature to detect, use values in SunflowerConstants.cs</param>
				/// <param name="culling">The type of culling to use, use values in SunflowerConstants.cs</param>
				/// <returns>The actual number of features found</returns>
				static int FindFeaturePoints(BYTE *image, int width, int height, int stride, int maxFeatures, float *x, float *y, int detector, int culling);
			};
        }
    }
}
